<template>
  <view>
    <xl-popup v-model="isVisible" direction="bottom" :padding="0" :borderRadius="[20, 20, 0, 0]" :zIndex="zIndex">
      <view class="popup-box">
        <view class="product-wrapper">
          <view class="face">
            <xl-image class="face_image" :src="faceUrl"></xl-image>
          </view>
          <view class="info">
            <view class="price">
              <text>{{ priceTxt }}</text>
              <text v-if="priceUnit" class="unit">{{ priceUnit }}</text>
            </view>
            <view class="tip">{{ specTxt }}</view>
          </view>
        </view>
        <view class="spec-wrapper">
          <scroll-view scroll-y="true" class="spec-scroll">
            <view class="content">
              <slot name="header"/>
              <xl-spec
                  :color="color"
                  :specList="specList"
                  :skuList="skuList"
                  :curSpec="curSpec"
                  @change="changeSpec"
              ></xl-spec>
              <view v-if="showStock" class="num-box flex">
                <view class="label">数量</view>
                <view class="flex-between flex-1">
                  <view v-if="openStock" class="stock">库存 {{ curSpecProduct ? curSpecProduct[stockName] : 0 }}</view>
                  <view v-else></view>
                  <xl-number
                      v-model="productNum"
                      :disabled="!curSpecProduct || openStock && curSpecProduct[stockName] <= 0"
                      :min="1"
                      :max="openStock && curSpecProduct ? curSpecProduct[stockName] : 0"
                      :inputColor="color"
                      width="220"
                      height="55"
                  ></xl-number>
                </view>
              </view>
              <slot/>
            </view>
          </scroll-view>
        </view>
        <view v-if="type === 'both'" class="flex-center">
          <xl-button
              :color="`linear-gradient(to right, ${btnColors[1]}, ${btnColors[0]})`"
              shape="circle"
              margin="30rpx 0 0"
              :disabled="!enabled"
              style="flex: 1;"
              customStyle="border-top-right-radius: 0;border-bottom-right-radius: 0;font-size: 32rpx;font-weight:bold;"
              @click="confirmCart"
          >{{cartName}}</xl-button>
          <xl-button
              :color="isEmptyStock ? '#a9a9a9' : `linear-gradient(to right, ${btnColors[0]}, ${btnColors[1]})`"
              shape="circle"
              margin="30rpx 0 0"
              :disabled="!enabled"
              style="flex: 1;"
              customStyle="border-top-left-radius: 0;border-bottom-left-radius: 0;font-size: 32rpx;font-weight:bold;"
              @click="confirmPay"
          >{{ isEmptyStock  ? emptyStockTxt : payName}}</xl-button>
        </view>
        <xl-button
            v-else
            :color="type !== 'cart' && isEmptyStock ? '#a9a9a9' : `linear-gradient(to right, ${btnColors[0]}, ${btnColors[1]})`"
            shape="circle"
            margin="30rpx 0 0"
            :disabled="!enabled"
            @click="confirm"
        >{{ type === 'cart' ? cartName : isEmptyStock  ? emptyStockTxt : payName}}</xl-button>
        <view class="close">
          <xl-icon name="xl-close-round" color="#b1b1b1" :size="20" @click="close"></xl-icon>
        </view>
      </view>
    </xl-popup>
  </view>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import propsData from './props.js'
const props = defineProps(propsData)
const emits = defineEmits(['update:modelValue', 'load', 'specsTxtChange', 'stockTotalChange', 'cartConfirm', 'payConfirm'])
defineExpose({ load })
const isVisible = computed({
  get() {
    return props.modelValue
  },
  set(value) {
    emits('update:modelValue', value)
  }
})

function close() {
  isVisible.value = false
}

const specList = ref([])
const skuList = ref([])
// 规格列表变化更新
watch(() => props.specs, newVal => {
  // props.specs有可能是json字符串
  specList.value = newVal ? typeof specs === 'string' ? JSON.parse(newVal) : Array.isArray(newVal) ? props.specs : [] : []
}, { immediate: true })

// 规格产品列表变化更新
watch(() => props.products, newVal => {
  updateProduct(props.products)
}, { immediate: true })

watch(() => props.productId, newVal => {
  if(newVal) {
    if(props.specApi) {
      if(!uni.$xl.apis[props.specApi]) {
        console.error('您配置的specApi接口方法不存在')
      } else {
        uni.$xl.apis[props.specApi]({
          jointUrl: '/' + props.productId
        }).then(res =>{
          updateSpec(props.specs, res.data)
        })
      }
    } else {
      load()
    }
  }
}, { immediate: true })

function load() {
  emits('load', props.productId, updateProduct)
}

function updateProduct(products) {
  // 请求商品sku之后，默认选择第一个可选规格
  skuList.value = products.map(item => {
    if(typeof item.spec === 'string') {
      item.spec = JSON.parse(item.spec)
    }
    if(typeof item.spec === 'object' && !Array.isArray(item.spec)) {
      item.spec = Object.values(item.spec)
    }
    return item
  })
}

// 价格显示，分转为元，保留两位小数
function priceFormat(price) {
  price = price || 0
  return props.isFen ? `${(price / 100).toFixed(2)}` : price
}

// 设置价格区间
const maxPrice = ref(0)
const minPrice = ref(0)
function setPriceMinAndMax(productList) {
  if(!productList || !productList.length) {
    productList = skuList.value
  }
  maxPrice.value = 0
  minPrice.value = Infinity
  productList.forEach(product => {
    if(product[props.priceName] < minPrice.value) {
      minPrice.value = product[props.priceName]
    }
    if(product[props.priceName] > maxPrice.value) {
      maxPrice.value = product[props.priceName]
    }
  })
  if(minPrice.value === Infinity) minPrice.value = 0
}

// 价格文本
const priceTxt = computed(v => {
  if(curSpecProduct.value) {
    return '¥' + priceFormat(curSpecProduct.value[props.priceName])
  } else if(maxPrice.value === minPrice.value) {
    return '¥' + priceFormat(maxPrice.value)
  } else {
    return '¥' + priceFormat(minPrice.value) + " ~ ¥" + priceFormat(maxPrice.value)
  }
})

// 设置规格文本
const specTxt = ref('')
function setSpecTxt(value, all, none, choose, unChoose) {
  if(all) {
    specTxt.value = '已选：' + value.join('，')
  } else {
    specTxt.value = '请选择：' + unChoose.join('，')
  }
}

const isEmptyStock = computed(() =>
    props.openStock &&
    (!skuList.value.length || curSpecProduct.value && curSpecProduct.value[props.stockName] < 1))
// 当前规格产品
const curSpecProduct = ref(undefined)
const imageUrl = ref('')
const faceUrl = computed(() => imageUrl.value || props.face)
function changeSpec({ value, product, productList, all, none, choose, unChoose, image }) {
  curSpecProduct.value = product
  setSpecTxt(value, all, none, choose, unChoose)
  setPriceMinAndMax(productList)
  imageUrl.value = image
  emits('specsTxtChange', specTxt.value)
  emits('stockTotalChange', curSpecProduct.value ? curSpecProduct.value[props.stockName] : 0)
}
const productNum = ref(1)

const enabled = computed(()=>{
  if (curSpecProduct.value) return !props.openStock || curSpecProduct.value[props.stockName] >= productNum.value
  else return false
})

function confirmCart(){
  emits('cartConfirm', curSpecProduct.value, productNum.value)
  close()
}

function confirmPay(){
  emits('payConfirm', curSpecProduct.value, productNum.value)
  close()
}

function confirm() {
  if(props.type == 'cart') emits('cartConfirm', curSpecProduct.value, productNum.value)
  else emits('payConfirm', curSpecProduct.value, productNum.value)
  close()
}
</script>

<style lang="scss" scoped>
.popup-box {
  height: 1060rpx;
  padding: 30rpx;
  position: relative;
}
.product-wrapper {
  height: 180rpx;
  display: flex;
  .face {
    width: 160rpx;
    height: 160rpx;
  }
  .info {
    flex: 1;
    margin-left: 30rpx;
    margin-top: 30rpx;
    .price {
      color: #ea4e4d;
      font-size: 44rpx;
      height: 60rpx;
      line-height: 60rpx;
      .unit {
        font-size: 28rpx;
        margin-top: 10rpx;
        margin-left: 10rpx;
        margin-right: 12rpx;
      }
    }
    .tip {
      margin-top: 10rpx;
      color: #999;
      font-size: 28rpx;
    }
  }
}
.spec-wrapper {
  width: 100%;
  overflow: hidden;
}
.spec-scroll {
  width: calc(100% + 24rpx);
  height: 780rpx;
  border-top: 1rpx solid #f1f1f1;
  .content {
    padding-right: 24rpx;
    padding-top: 30rpx;
  }
  .num-box {
    padding-top: 30rpx;
    padding-bottom: 20rpx;
    display: flex;
    align-items: center;
    .label {
      font-weight: 700;
      color: #333;
      font-size: 32rpx;
      margin-right: 20rpx;
    }
    .stock {
      color: #b1b1bb;
      font-size: 24rpx;
    }
  }
}
.close {
  position: absolute;
  top: 20rpx;
  right: 20rpx;
  width: 40rpx;
  height: 40rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>